import * as TWEEN from "@tweenjs/tween.js";
import * as THREE from "three";
import { useCurrentModelStore } from "@/stores/current";
import { Base3DGroup, AnimateGroup } from "../types/DrawingGroups/groups";

const drawerDepthRatio = 0.7;
const duration = 1000; //时间

//执行开门动画（包括各种方向的门和抽屉）
export function AnimateDoorOpen(doorGroup: Base3DGroup) {
  const [anigroup] = doorGroup.children.filter(
    (it) => it instanceof AnimateGroup
  );
  if (anigroup && anigroup.isDoorOpen) {
    return; //检查状态，如果是已经开着的，就跳出函数
  }

  const [model] = doorGroup.model.kujialeModel!;

  const parameterDir = model.parameters.find(
    (it) => it.name === "openDirection"
  ); //变量，开门方向

  if (parameterDir && parameterDir.value == "4") {
    return; //开门方向4，无方向
  }

  const parameterType = model.parameters.find((it) => it.name === "doorType"); //门板类型
  if (parameterType && parameterType.value == "1") {
    return; //假门
  }

  const parameterW = model.parameters.find((it) => it.name === "W"); //组件的宽高深变量
  const parameterH = model.parameters.find((it) => it.name === "H"); //组件的宽高深变量
  const parameterD = model.parameters.find((it) => it.name === "D"); //组件的宽高深变量,由于有的门是空的，默认20

  if (parameterW && parameterH) {
    //门板的旋转，根据开门方式不同，旋转轴也不一样，左开门时是左下，右开门就是右下，并不是group的坐标
    //所以为了让门板组件可以绕着右下旋转，只好做一个新的group将其包裹住，而将新group的坐标则为旋转点

    //获取宽高深
    const w = parseFloat(parameterW.value as string);
    const h = parseFloat(parameterH.value as string);
    const d =
      parameterD === undefined ? 20 : parseFloat(parameterD.value as string);

    //创建一个新的group，插入到门板组件中
    //原来的门板组件group做定位用，新group做旋转用，原来的绘制元素添加到新group底下
    //旋转的中心点，是新group的坐标
    const wrapGroup = anigroup || new AnimateGroup();
    wrapGroup.name = "wrap door animate group";

    //在doorgroup中创建一个新group，把原来doorGroup的子元素都加入到这个新group中
    //相关动画操作只和这个新group相关
    while (doorGroup.children.length > 0) {
      wrapGroup.add(doorGroup.children[0]);
    } //用while而不是forEach，由于group.add操作会导致index变化，导致forEach不能遍历所有
    doorGroup.add(wrapGroup);

    if (model.prodCatId == 498 && parameterDir && parameterType) {
      if (parameterType.value == "0") {
        if (parameterDir.value == "0") {
          //左开门
          animateDoorLeftOpen(wrapGroup, d);
        } else if (parameterDir.value == "1") {
          //右开门
          animateDoorRightOpen(wrapGroup, w, d);
        } else if (parameterDir.value == "2") {
          //上翻门
          animateDoorUpOpen(wrapGroup, h, d);
        } else if (parameterDir.value == "3") {
          //下翻门
          animateDoorDownOpen(wrapGroup, d);
        }
      }
    } else if (model.prodCatId == 1043 && parameterD) {
      //抽屉
      const d = parseFloat(parameterD.value as string);
      animateDrawerOpen(wrapGroup, d);
    }
  }
}

function animateDrawerOpen(wrapGroup: AnimateGroup, depth: number) {
  const tween = new TWEEN.Tween(wrapGroup.position)
    .to(
      {
        z: wrapGroup.position.z + depth * drawerDepthRatio,
      },
      duration
    )
    .easing(TWEEN.Easing.Sinusoidal.InOut);
  tween.onComplete((o) => {
    wrapGroup.isDoorOpen = true;
  });
  const store = useCurrentModelStore();
  store.currentTWEENGRoup?.add(tween);
  tween.start();
}

function animateDoorUpOpen(
  wrapGroup: AnimateGroup,
  height: number,
  depth: number
) {
  //将新group的坐标，设为旋转中心
  wrapGroup.position.set(0, height, 0);
  //门组件的坐标跟着偏移
  wrapGroup.children.forEach((c) =>
    c.position.add(new THREE.Vector3(0, -height, 0))
  );

  const tween = new TWEEN.Tween(wrapGroup)
    .to(
      {
        rotation: {
          x: wrapGroup.rotation.x - Math.PI / 2,
        },
        position: {
          y: wrapGroup.position.y - depth,
        },
      },
      duration
    )
    .easing(TWEEN.Easing.Sinusoidal.InOut);
  tween.onComplete((o) => {
    wrapGroup.isDoorOpen = true;
  });
  const store = useCurrentModelStore();
  store.currentTWEENGRoup?.add(tween);
  tween.start();
}

function animateDoorDownOpen(wrapGroup: AnimateGroup, depth: number) {
  const tween = new TWEEN.Tween(wrapGroup)
    .to(
      {
        rotation: {
          x: wrapGroup.rotation.x + Math.PI / 2,
        },
        position: {
          y: wrapGroup.position.y + depth,
        },
      },
      duration
    )
    .easing(TWEEN.Easing.Sinusoidal.InOut);
  tween.onComplete((o) => {
    wrapGroup.isDoorOpen = true;
  });
  const store = useCurrentModelStore();
  store.currentTWEENGRoup?.add(tween);
  tween.start();
}

function animateDoorLeftOpen(wrapGroup: AnimateGroup, depth: number) {
  //将新group的坐标，设为旋转中心
  wrapGroup.position.set(0, 0, 0);
  //门组件的坐标跟着偏移
  wrapGroup.children.forEach((c) => c.position.add(new THREE.Vector3(0, 0, 0)));

  const tween = new TWEEN.Tween(wrapGroup)
    .to(
      {
        rotation: {
          y: wrapGroup.rotation.y + -Math.PI / 2,
        },
        position: {
          x: wrapGroup.position.x + depth,
        },
      },
      duration
    )
    .easing(TWEEN.Easing.Sinusoidal.InOut);
  // const tween = new TWEEN.Tween(wrapGroup.rotation)
  //   .to(
  //     {
  //       y: wrapGroup.rotation.y + -Math.PI / 2,
  //     },
  //     duration
  //   )
  //   .easing(TWEEN.Easing.Sinusoidal.InOut);

  tween.onComplete((o) => {
    wrapGroup.isDoorOpen = true;
  });
  const store = useCurrentModelStore();
  store.currentTWEENGRoup?.add(tween);
  tween.start();
}

function animateDoorRightOpen(
  wrapGroup: AnimateGroup,
  width: number,
  depth: number
) {
  //将新group的坐标，设为旋转中心
  wrapGroup.position.set(width, 0, 0);
  //门组件的坐标跟着偏移
  wrapGroup.children.forEach((c) =>
    c.position.add(new THREE.Vector3(-width, 0, 0))
  );

  const tween = new TWEEN.Tween(wrapGroup)
    .to(
      {
        rotation: {
          y: wrapGroup.rotation.y + Math.PI / 2,
        },
        position: {
          x: wrapGroup.position.x - depth,
        },
      },
      duration
    )
    .easing(TWEEN.Easing.Sinusoidal.InOut);
  tween.onComplete((o) => {
    wrapGroup.isDoorOpen = true;
  });
  const store = useCurrentModelStore();
  store.currentTWEENGRoup?.add(tween);
  tween.start();
}

export function AnimateDoorClose(doorGroup: Base3DGroup) {
  //找到特定的组，并把他们用动画转回去，并取消这个组，还原到初始状态
  if (doorGroup.children.length != 1) {
    return;
  }

  const [animategroup] = doorGroup.children;
  if (!(animategroup instanceof AnimateGroup)) {
    return;
  }

  const store = useCurrentModelStore();
  const [model] = doorGroup.model.kujialeModel!;

  const parameterDir = model.parameters.find(
    (it) => it.name === "openDirection"
  );
  if (parameterDir && parameterDir.value == "4") {
    return; //开门方向4，无方向
  }

  const parameterType = model.parameters.find((it) => it.name == "doorType");
  if (parameterType && parameterType.value == "1") {
    return; //假门
  }
  //组件的宽高深变量
  const parameterW = model.parameters.find((it) => it.name === "W");
  const parameterH = model.parameters.find((it) => it.name === "H");
  const parameterD = model.parameters.find((it) => it.name === "D");

  if (parameterW && parameterH) {
    //门板的旋转，根据开门方式不同，旋转轴也不一样，左开门时是左下，右开门就是右下，并不是group的坐标
    //所以为了让门板组件可以绕着右下旋转，只好做一个新的group将其包裹住，而将新group的坐标则为旋转点

    //获取宽高深
    const w = parseFloat(parameterW.value as string);
    const h = parseFloat(parameterH.value as string);
    const d =
      parameterD == undefined ? 20 : parseFloat(parameterD.value as string);

    if (model.prodCatId == 498 && parameterDir && parameterType) {
      if (parameterType.value == "0") {
        if (parameterDir.value == "0") {
          //左开门
          animateDoorLeftClose(animategroup, d);
        } else if (parameterDir.value == "1") {
          //右开门
          animateDoorRightClose(animategroup, w, d);
        } else if (parameterDir.value == "2") {
          //上翻门
          animateDoorUpClose(animategroup, h, d);
        } else if (parameterDir.value == "3") {
          //下翻门
          animateDoorDownClose(animategroup, d);
        }
      }
    } else if (model.prodCatId == 1043 && parameterD) {
      //抽屉
      const d = parseFloat(parameterD.value as string);
      animateDrawerClose(animategroup, d);
    }
  }
}

function animateDrawerClose(wrapGroup: AnimateGroup, depth: number) {
  const tween = new TWEEN.Tween(wrapGroup.position)
    .to(
      {
        z: wrapGroup.position.z - depth * drawerDepthRatio,
      },
      duration
    )
    .easing(TWEEN.Easing.Sinusoidal.InOut);
  tween.onComplete((o) => {
    wrapGroup.isDoorOpen = false;
    //把动画组的成员都加回门板组
    let doorGroup = wrapGroup.parent;
    while (wrapGroup.children.length > 0) {
      doorGroup!.add(wrapGroup.children[0]);
    } //用while而不是forEach，由于group.add操作会导致index变化，导致forEach不能遍历所有
    doorGroup!.remove(wrapGroup);
  });
  const store = useCurrentModelStore();
  store.currentTWEENGRoup?.add(tween);
  tween.start();
}

function animateDoorLeftClose(animategroup: AnimateGroup, d: number) {
  const tween = new TWEEN.Tween(animategroup)
    .to(
      {
        rotation: {
          y: animategroup.rotation.y + Math.PI / 2,
        },
        position: {
          x: animategroup.position.x - d,
        },
      },
      duration
    )
    .easing(TWEEN.Easing.Sinusoidal.InOut);
  tween.onComplete((o) => {
    animategroup.isDoorOpen = false;
    var doorGroup = animategroup.parent;
    //把动画组的成员都加回门板组
    while (animategroup.children.length > 0) {
      doorGroup!.add(animategroup.children[0]);
    } //用while而不是forEach，由于group.add操作会导致index变化，导致forEach不能遍历所有
    doorGroup!.remove(animategroup);
  });
  const store = useCurrentModelStore();
  store.currentTWEENGRoup?.add(tween);
  tween.start();
}

function animateDoorRightClose(
  animategroup: AnimateGroup,
  w: number,
  d: number
) {
  const tween = new TWEEN.Tween(animategroup)
    .to(
      {
        rotation: {
          y: animategroup.rotation.y + (-1 * Math.PI) / 2,
        },
        position: {
          x: animategroup.position.x + d,
        },
      },
      duration
    )
    .easing(TWEEN.Easing.Sinusoidal.InOut);
  var doorGroup = animategroup.parent;
  tween.onComplete((o) => {
    animategroup.isDoorOpen = false;
    //把动画组的成员都加回门板组
    while (animategroup.children.length > 0) {
      doorGroup!.add(animategroup.children[0]);
    } //用while而不是forEach，由于group.add操作会导致index变化，导致forEach不能遍历所有
    doorGroup!.remove(animategroup);

    //门组件的坐标跟着偏移
    doorGroup!.children.forEach((c) =>
      c.position.add(new THREE.Vector3(w, 0, 0))
    );
  });
  const store = useCurrentModelStore();
  store.currentTWEENGRoup?.add(tween);
  tween.start();
}

function animateDoorUpClose(
  animategroup: AnimateGroup,
  height: number,
  depth: number
) {
  const tween = new TWEEN.Tween(animategroup)
    .to(
      {
        rotation: {
          x: animategroup.rotation.x + Math.PI / 2,
        },
        position: {
          y: animategroup.position.y + depth,
        },
      },
      duration
    )
    .easing(TWEEN.Easing.Sinusoidal.InOut);
  var doorGroup = animategroup.parent;
  tween.onComplete((o) => {
    animategroup.isDoorOpen = false;
    //把动画组的成员都加回门板组
    while (animategroup.children.length > 0) {
      doorGroup!.add(animategroup.children[0]);
    } //用while而不是forEach，由于group.add操作会导致index变化，导致forEach不能遍历所有
    doorGroup!.remove(animategroup);

    //门组件的坐标跟着偏移
    doorGroup!.children.forEach((c) =>
      c.position.add(new THREE.Vector3(0, height, 0))
    );
  });
  const store = useCurrentModelStore();
  store.currentTWEENGRoup?.add(tween);
  tween.start();
}

function animateDoorDownClose(animategroup: AnimateGroup, depth: number) {
  const tween = new TWEEN.Tween(animategroup)
    .to(
      {
        rotation: {
          x: animategroup.rotation.x - Math.PI / 2,
        },
        position: {
          y: animategroup.position.y - depth,
        },
      },
      duration
    )
    .easing(TWEEN.Easing.Sinusoidal.InOut);
  var doorGroup = animategroup.parent;
  tween.onComplete((o) => {
    animategroup.isDoorOpen = false;
    //把动画组的成员都加回门板组
    while (animategroup.children.length > 0) {
      doorGroup!.add(animategroup.children[0]);
    } //用while而不是forEach，由于group.add操作会导致index变化，导致forEach不能遍历所有
    doorGroup!.remove(animategroup);
  });
  const store = useCurrentModelStore();
  store.currentTWEENGRoup?.add(tween);
  tween.start();
}
